import json
import logging
import uuid
from datetime import datetime

from sqlalchemy import select, false
import requests
from sqlalchemy.exc import SQLAlchemyError

from configs import web_config
from models import db
from models.rule import SimilarTask
from api.service.simliar_index_service import matcher as matcher_service

logger = logging.getLogger(__name__)


def submit_task(request_body: str):
    try:
        task_id = str(uuid.uuid4())  # 生成唯一任务ID
        task = SimilarTask(
            task_id=task_id,
            request=request_body,
            status=0,  # pending
            create_time=datetime.utcnow()
        )
        db.session.add(task)
        db.session.commit()
        db.session.refresh(task)
        return {
            "task_id": task.task_id,
            "status": task.status
        }
    except Exception as e:
        logger.error(f"Unexpected error in submit_task: {e}", exc_info=True)
        db.session.rollback()  # 记得回滚


# 定时任务：处理 pending 的任务
def process_pending_tasks():
    try:
        # 查询所有 status=0 且未超过重试上限的任务
        stmt = (
            select(SimilarTask)
            .where(SimilarTask.status == 0)
            .where(SimilarTask.times < web_config.MAX_RETRY_TIMES)
            # 可选：加锁防止并发重复处理
            # .with_for_update(skip_locked=True)  # 需要 SQLAlchemy 1.4+ 和数据库支持
        )
        result = db.session.execute(stmt)
        tasks = result.scalars().all()

        if not tasks:
            logger.info("No pending tasks to process.")
            return

        success_count = 0
        failed_count = 0

        for task in tasks:
            try:
                req_data = json.loads(task.request)
                response = process_result(req_data)

                task.match = json.dumps(response, ensure_ascii=False, indent=2)
                task.status = 1  # success
                success_count += 1

            except Exception as e:
                error_msg = f"Task {task.id} failed: {str(e)}"
                logger.exception(error_msg)  # 记录完整 traceback

                task.response = str(e)
                task.status = -1  # failed
                failed_count += 1

            finally:
                task.times += 1
                db.session.add(task)  # 确保加入 session

        # ✅ 所有任务处理完后统一提交
        try:
            db.session.commit()
            logger.info(f"Processed {len(tasks)} tasks: {success_count} success, {failed_count} failed.")
        except SQLAlchemyError as e:
            db.session.rollback()
            logger.error(f"Database commit failed: {e}", exc_info=True)
            raise  # 可选择重新抛出，由上层调度器重试

    except Exception as e:
        logger.error(f"Unexpected error in process_pending_tasks: {e}", exc_info=True)
        db.session.rollback()
        raise


def send_result(data):
    headers = {
        "Content-Type": "application/json"
    }
    try:
        # 发送 POST 请求
        print(json.dumps(data))
        response = requests.post(web_config.REQUEST_URL, data=json.dumps(data), headers=headers)
        # 检查响应状态码
        if response.status_code == 200:
            print("POST 请求发送成功！")
            print("响应内容:", response.json())  # 假设返回的是 JSON
        else:
            print(f"请求失败，状态码: {response.status_code}")
            print("响应内容:", response.text)

    except requests.exceptions.RequestException as e:
        # 处理网络异常（如连接超时、DNS错误等）
        print("发送请求时发生错误:", e)


def process_result(req_data):
    response = {"meta": req_data.get("meta")}
    items = []
    for item in req_data["data"]:
        results = matcher_service.find_most_similar(
            current=item,
            top_k=req_data.get("meta").get("top_k", 1),
            min_match_count=req_data.get("meta").get("min_match_field", 1),
            category=req_data.get("data").get("tree_id", "default")
        )
        similar_results = get_similar_results(results)
        obj = {"input_fact": item, "similar_results": similar_results,
               "statistics": {"max_similarity": get_max_similarity(similar_results)}}
        items.append(obj)
    response["data"] = items
    return response


def get_similar_results(results):
    similar_results = []
    index = 0
    for result in results:
        index = index + 1
        attributes = []
        for key, value in result["candidate"].items():
            attributes.append({"name": key, "value": value,
                               "equals": 1 if key in result["matched_attrs"] else 0})
        obj = {"similarity": result["match_rate"], "is_subsidiary_preferred": is_subsidiary_preferred(),
               "is_global_procurement_preferred": is_global_procurement_preferred(),
               "is_unified_preferred": is_unified_preferred(), "order_index": index, "attributes": attributes}
        similar_results.append(obj)
    return similar_results


def get_max_similarity(similar_results):
    return similar_results[0]["similarity"]


def is_subsidiary_preferred():
    return false


def is_global_procurement_preferred():
    return false


def is_unified_preferred():
    return false


def get_task_result(task_id: str):
    stmt = select(SimilarTask).where(SimilarTask.task_id == task_id)
    result = db.session.execute(stmt)
    task = result.scalar_one_or_none()
    if not task:
        return None
    return task.match
